package com.yunyao.framework.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.yunyao.common.constant.enums.DataDeletedStatus;
import com.yunyao.common.constant.enums.SupplyListStatus;
import com.yunyao.common.dto.supplier.ContractDto;
import com.yunyao.common.dto.SoSupplyDto;
import com.yunyao.common.web.enums.ResultMsgEnum;
import com.yunyao.common.web.util.ConvertUtil;
import com.yunyao.common.web.util.PageResult;
import com.yunyao.common.web.util.StringUtils;
import com.yunyao.common.web.util.YResult;
import com.yunyao.dao.model.*;
import com.yunyao.dao.service.bamu.*;
import com.yunyao.framework.dto.soSupply.SoSupplyMaterialDeletedDto;
import com.yunyao.framework.dto.soSupply.SoSupplyMaterialDto;
import com.yunyao.framework.dto.contract.ContractNodePaySaveDto;
import com.yunyao.framework.dto.contract.ContractWirePaySaveDto;
import com.yunyao.framework.dto.soSupply.SoSupplyMaterialInfoSaveDto;
import com.yunyao.framework.dto.soSupply.SoSupplyMaterialSaveDto;
import com.yunyao.framework.service.SoSupplyOrderService;
import com.yunyao.framework.vo.contract.ContractNodePayVO;
import com.yunyao.framework.vo.contract.ContractWirePayVO;
import com.yunyao.framework.vo.sosyupply.SoSupplyMaterialVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SoSupplyOrderServiceImpl implements SoSupplyOrderService {

    @Autowired
    private IBamuSoSupplyMaterialService iBamuSoSupplyMaterialService;

    @Autowired
    private IBamuPoSupplyMaterialService iBamuPoSupplyMaterialService;
    @Autowired
    private IBamuSoSupplyService iBamuSoSupplyService;

    @Autowired
    private IBamuPoSupplyService iBamuPoSupplyService;
    @Autowired
    private IBamuContractNodePayService iBamuContractNodePayService;

    @Autowired
    private IBamuContractWirePayService iBamuContractWirePayService;

    @Autowired
    private IBamuPurchaseApplyMaterialService iBamuPurchaseApplyMaterialService;

    @Autowired
    private IBamuSupplyApplyMaterialService iBamuSupplyApplyMaterialService;


    @Override
    public YResult<PageResult<SoSupplyMaterialVO>> getPoSupplyMaterialList(SoSupplyMaterialDto soSupplyMaterialDto) {
        // 构建查询条件
        String contractId = soSupplyMaterialDto.getContractId();
        String purchaseApplyId = soSupplyMaterialDto.getPurchaseApplyId();
        LambdaQueryWrapper<BamuSoSupplyMaterial> wrapper = new LambdaQueryWrapper<BamuSoSupplyMaterial>()
                .eq(StringUtils.isNotEmpty(purchaseApplyId), BamuSoSupplyMaterial::getPurchaseApplyId, purchaseApplyId)
                .eq(BamuSoSupplyMaterial::getSupplyId, soSupplyMaterialDto.getId())
                .eq(BamuSoSupplyMaterial::getIsDeleted, DataDeletedStatus.NO.getType());
        // 分页查询
        IPage<BamuSoSupplyMaterial> payPage = new Page<>(soSupplyMaterialDto.getPageIndex(), soSupplyMaterialDto.getPageSize());
        payPage = iBamuSoSupplyMaterialService.page(payPage, wrapper);

        // 处理查询结果
        if (CollectionUtils.isEmpty(payPage.getRecords())) {
            return YResult.success(new PageResult<>());
        }

        // 转换为VO对象列表
        List<SoSupplyMaterialVO> materialVOList = materialDaoToVoList(payPage.getRecords());

        // 返回分页结果
        return YResult.success(new PageResult<>(materialVOList, payPage.getCurrent(), payPage.getSize(), payPage.getPages(), payPage.getTotal()));

    }

    @Override
    public YResult<PageResult<SoSupplyMaterialVO>> getPoSupplyMaterialListbySupplyId(SoSupplyMaterialDto soSupplyMaterialDto) {
        // 构建查询条件
//        String contractId = soSupplyMaterialDto.getContractId();
//        String purchaseApplyId = soSupplyMaterialDto.getPurchaseApplyId();
        LambdaQueryWrapper<BamuSoSupplyMaterial> wrapper = new LambdaQueryWrapper<BamuSoSupplyMaterial>()
                .in(BamuSoSupplyMaterial::getSupplyId, soSupplyMaterialDto.getIdList())// 使用in方法查询ID列表中的任意一个
//                .eq(BamuSoSupplyMaterial::getPurchaseApplyId, purchaseApplyId)
                .eq(BamuSoSupplyMaterial::getIsDeleted, DataDeletedStatus.NO.getType());
        // 分页查询
        IPage<BamuSoSupplyMaterial> payPage = new Page<>(soSupplyMaterialDto.getPageIndex(), soSupplyMaterialDto.getPageSize());
        payPage = iBamuSoSupplyMaterialService.page(payPage, wrapper);

        // 处理查询结果
        if (CollectionUtils.isEmpty(payPage.getRecords())) {
            return YResult.success(new PageResult<>());
        }

        // 转换为VO对象列表
        List<SoSupplyMaterialVO> materialVOList = materialDaoToVoList(payPage.getRecords());

        // 返回分页结果
        return YResult.success(new PageResult<>(materialVOList, payPage.getCurrent(), payPage.getSize(), payPage.getPages(), payPage.getTotal()));

    }

    @Override
    public BigDecimal getBySupplyId(List<String> bizIds) {
        if (CollectionUtils.isEmpty(bizIds)) {
            return BigDecimal.ZERO;
        }
        List<BamuSoSupplyMaterial> list = iBamuSoSupplyMaterialService.lambdaQuery()
                .in(BamuSoSupplyMaterial::getSupplyId, bizIds)
                .eq(BamuSoSupplyMaterial::getIsDeleted, DataDeletedStatus.NO.getType())
                .list();
        if (CollectionUtils.isEmpty(list)) {
            return BigDecimal.ZERO;
        }
        return list
                .stream()
                .map(BamuSoSupplyMaterial::getIncludingTaxTotalPrice)
                .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
    }


    @Override
    public YResult<ContractWirePayVO> getWirePayInfo(ContractDto contractDto) {
        String contractId = contractDto.getContractId();
        LambdaQueryWrapper<BamuContractWirePay> wrapper = new LambdaQueryWrapper<BamuContractWirePay>()
                .eq(BamuContractWirePay::getContractId, contractId)
                .eq(BamuContractWirePay::getIsDeleted, DataDeletedStatus.NO.getType());
        BamuContractWirePay bamuContractWirePay = iBamuContractWirePayService.getOne(wrapper);
        if (Objects.isNull(bamuContractWirePay)) {
            return YResult.success();
        }
        ContractWirePayVO contractWirePayVO = wirePayDaoToVo(bamuContractWirePay);
        return YResult.success(contractWirePayVO);
    }

    private ContractWirePayVO wirePayDaoToVo(BamuContractWirePay bamuContractWirePay) {
        ContractWirePayVO contractWirePayVO = new ContractWirePayVO();
        BeanUtils.copyProperties(bamuContractWirePay, contractWirePayVO);
        return contractWirePayVO;
    }

    @Override
    public YResult<PageResult<ContractNodePayVO>> getContractNodePayList(ContractDto contractDto) {
        // 构建查询条件
        String contractId = contractDto.getContractId();
        LambdaQueryWrapper<BamuContractNodePay> wrapper = new LambdaQueryWrapper<BamuContractNodePay>()
                .eq(BamuContractNodePay::getContractId, contractId)
                .eq(BamuContractNodePay::getIsDeleted, DataDeletedStatus.NO.getType());
        // 分页查询
        IPage<BamuContractNodePay> payPage = new Page<>(contractDto.getPageIndex(), contractDto.getPageSize());
        payPage = iBamuContractNodePayService.page(payPage, wrapper);

        // 处理查询结果
        if (CollectionUtils.isEmpty(payPage.getRecords())) {
            return YResult.success(new PageResult<>());
        }

        // 转换为VO对象列表
        List<ContractNodePayVO> nodePayVOList = nodePayDaoToVoList(payPage.getRecords());

        // 返回分页结果
        return YResult.success(new PageResult<>(nodePayVOList, payPage.getCurrent(), payPage.getSize(), payPage.getPages(), payPage.getTotal()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YResult<String> saveMaterialInfo(SoSupplyMaterialSaveDto saveDto) {
        List<SoSupplyMaterialInfoSaveDto> dtoList = saveDto.getMaterialList();
        if (CollectionUtils.isEmpty(dtoList)) {
            return YResult.error(ResultMsgEnum.PARAM_ERROR);
        }
        List<BamuSoSupplyMaterial> soSupplyMaterialList = materialDtoToDaoList(dtoList);
        if (CollectionUtils.isEmpty(soSupplyMaterialList)) {
            return YResult.error(ResultMsgEnum.PARAM_ERROR);
        }


        /**
         * 更新对应的验收清单
         */
        List<BamuPoSupplyMaterial> updatePoSupplyMaterialList = updatePoSupplyMaterialList(soSupplyMaterialList);

        if (CollectionUtils.isNotEmpty(updatePoSupplyMaterialList)) {
            iBamuPoSupplyMaterialService.saveOrUpdateBatch(updatePoSupplyMaterialList);
            iBamuSoSupplyMaterialService.saveOrUpdateBatch(soSupplyMaterialList, 20);


            /**
             * 更新项目订单中的验收数量
             */
            List<BamuPurchaseApplyMaterial> purchaseApplyMaterialList = iBamuPurchaseApplyMaterialService.getMaterialListByOrderId(soSupplyMaterialList.get(0).getPurchaseApplyId());
            updateBamuPurchaseApplyMaterialList(purchaseApplyMaterialList, soSupplyMaterialList);

            /**
             * 更新供货订单中的验收数量
             */
            List<BamuSupplyApplyMaterial> supplyApplyMaterialList = iBamuSupplyApplyMaterialService.getMaterialListByOrderId(updatePoSupplyMaterialList.get(0).getPurchaseApplyId());
            updateBamuSupplyApplyMaterialList(supplyApplyMaterialList, updatePoSupplyMaterialList);


            /**
             * 保存订单材料
             */
            iBamuPurchaseApplyMaterialService.saveOrUpdateBatch(purchaseApplyMaterialList);
            iBamuSupplyApplyMaterialService.saveOrUpdateBatch(supplyApplyMaterialList);
        }

        return YResult.success(saveDto.getId());
    }

    /**
     * 更新项目订单中的验收数量
     *
     * @param applyMaterialList 项目订单材料
     * @param soSupplyList      验收清单材料
     */
    private void updateBamuPurchaseApplyMaterialList(List<BamuPurchaseApplyMaterial> applyMaterialList, List<BamuSoSupplyMaterial> soSupplyList) {
        Map<String, BigDecimal> map = soSupplyList.stream().filter(x -> null != x.getComfirmSupplyNum()).collect(Collectors.toMap(BamuSoSupplyMaterial::getMaterialCode, BamuSoSupplyMaterial::getComfirmSupplyNum, BigDecimal::add));
        if (null != map && map.size() > 0 && CollectionUtils.isNotEmpty(applyMaterialList)) {
            for (BamuPurchaseApplyMaterial applyMaterial : applyMaterialList) {
                if (map.containsKey(applyMaterial.getMaterialCode())) {
                    applyMaterial.setCheckNum(ConvertUtil.getBigDecimalValue(applyMaterial.getCheckNum()).add(map.get(applyMaterial.getMaterialCode())));
                }
            }
        }
    }


    /**
     * 更新供货订单中的验收数量
     *
     * @param applyMaterialList 供货订单材料
     * @param poSupplyList      供货清单材料
     */
    private void updateBamuSupplyApplyMaterialList(List<BamuSupplyApplyMaterial> applyMaterialList, List<BamuPoSupplyMaterial> poSupplyList) {
        Map<String, BigDecimal> map = poSupplyList.stream().filter(x -> null != x.getComfirmSupplyNum()).collect(Collectors.toMap(BamuPoSupplyMaterial::getMaterialCode, BamuPoSupplyMaterial::getComfirmSupplyNum, BigDecimal::add));
        if (null != map && map.size() > 0 && CollectionUtils.isNotEmpty(applyMaterialList)) {
            for (BamuSupplyApplyMaterial applyMaterial : applyMaterialList) {
                if (map.containsKey(applyMaterial.getMaterialCode())) {
                    applyMaterial.setCheckNum(ConvertUtil.getBigDecimalValue(applyMaterial.getCheckNum()).add(map.get(applyMaterial.getMaterialCode())));
                }
            }
        }
    }

    private List<BamuPoSupplyMaterial> updatePoSupplyMaterialList(List<BamuSoSupplyMaterial> daoList) {
        List<BamuPoSupplyMaterial> updatePoSupplyMaterialList = new ArrayList<>();
        if (CollectionUtils.isEmpty(daoList)) {
            return updatePoSupplyMaterialList;
        }
        for (BamuSoSupplyMaterial bamuSoSupplyMaterial : daoList) {
            BamuPoSupplyMaterial poSupplyMaterial = iBamuPoSupplyMaterialService.getById(bamuSoSupplyMaterial.getPoSupplyMaterialId());
            if (Objects.nonNull(poSupplyMaterial)) {
                poSupplyMaterial.setComfirmSupplyNum(bamuSoSupplyMaterial.getComfirmSupplyNum());
                updatePoSupplyMaterialList.add(poSupplyMaterial);
            }
        }
        return updatePoSupplyMaterialList;
    }

    private List<BamuSoSupplyMaterial> materialDtoToDaoList(List<SoSupplyMaterialInfoSaveDto> dtoList) {
        return dtoList.stream().map(this::materialDtoToDao).collect(Collectors.toList());
    }

    private BamuSoSupplyMaterial materialDtoToDao(SoSupplyMaterialInfoSaveDto soSupplyMaterialInfoSaveDto) {
        BamuSoSupplyMaterial bamuSoSupplyMaterial = iBamuSoSupplyMaterialService.getById(soSupplyMaterialInfoSaveDto.getId());
        if (Objects.isNull(bamuSoSupplyMaterial)) {
            bamuSoSupplyMaterial = new BamuSoSupplyMaterial();
            BeanUtils.copyProperties(soSupplyMaterialInfoSaveDto, bamuSoSupplyMaterial);
        }
        bamuSoSupplyMaterial.setComfirmSupplyNum(soSupplyMaterialInfoSaveDto.getComfirmSupplyNum());
        return bamuSoSupplyMaterial;
    }

    @Override
    public YResult<String> savePayInfo(ContractWirePaySaveDto saveDto) {

        BamuContractWirePay contractWirePay = new BamuContractWirePay();
        BeanUtils.copyProperties(saveDto, contractWirePay);
        iBamuContractWirePayService.saveOrUpdate(contractWirePay);

        List<BamuContractNodePay> nodePayDtoToDaoList = nodePayDtoToDaoList(saveDto.getNodePaySaveDtoList());
        if (CollectionUtils.isNotEmpty(nodePayDtoToDaoList)) {
            iBamuContractNodePayService.saveBatch(nodePayDtoToDaoList);
        }
        return YResult.success(saveDto.getContractId());
    }

    @Override
    public YResult<String> deletedMaterialInfo(SoSupplyMaterialDeletedDto deletedDto) {
        if (CollectionUtils.isEmpty(deletedDto.getIdList())) {
            return YResult.error(ResultMsgEnum.PARAM_ERROR);
        }
        List<BamuSoSupplyMaterial> updateList = Lists.newArrayList();
        for (String id : deletedDto.getIdList()) {
            BamuSoSupplyMaterial soSupplyMaterial = new BamuSoSupplyMaterial();
            soSupplyMaterial.setId(id);
            soSupplyMaterial.setIsDeleted(DataDeletedStatus.YES.getType());
            updateList.add(soSupplyMaterial);
        }
        iBamuSoSupplyMaterialService.updateBatchById(updateList, 20);
        return YResult.success(deletedDto.getContractId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YResult<String> confirmFinish(SoSupplyDto orderDto) {
        BamuSoSupply bamuSoSupply = iBamuSoSupplyService.getById(orderDto.getId());
        bamuSoSupply.setSupplyStatus(SupplyListStatus.PROJECT_ACCEPTANCE_COMPLETED.getType());
        bamuSoSupply.setTakeAt(ConvertUtil.getString2Date(orderDto.getAuditDate()));
        bamuSoSupply.setTakeFiles(orderDto.getAuditFileUrl());
        bamuSoSupply.setTakeDesc(orderDto.getAuditReason());
        bamuSoSupply.setTakeUserName(orderDto.getRealName());
        bamuSoSupply.setTakeUserId(orderDto.getUserId());
        iBamuSoSupplyService.updateById(bamuSoSupply);

        LambdaQueryWrapper<BamuPoSupply> wrapper = new LambdaQueryWrapper<BamuPoSupply>();
        wrapper.eq(BamuPoSupply::getId, bamuSoSupply.getPoSupplyId());
        List<BamuPoSupply> poSupplyList = iBamuPoSupplyService.list(wrapper);
        if (CollectionUtils.isNotEmpty(poSupplyList)) {
            for (BamuPoSupply bamuPoSupply : poSupplyList) {
                bamuPoSupply.setSupplyStatus(SupplyListStatus.PROJECT_ACCEPTANCE_COMPLETED.getType());
                bamuPoSupply.setTakeAt(ConvertUtil.getString2Date(orderDto.getAuditDate()));
                bamuPoSupply.setTakeFiles(orderDto.getAuditFileUrl());
                bamuPoSupply.setTakeDesc(orderDto.getAuditReason());
                bamuPoSupply.setTakeUserName(orderDto.getRealName());
                bamuPoSupply.setTakeUserId(orderDto.getUserId());
            }
            iBamuPoSupplyService.updateBatchById(poSupplyList);
        }
        return YResult.success(bamuSoSupply.getId());
    }

    private List<BamuContractNodePay> nodePayDtoToDaoList(List<ContractNodePaySaveDto> nodePaySaveDtoList) {
        if (CollectionUtils.isEmpty(nodePaySaveDtoList)) {
            return Lists.newArrayList();
        }
        return nodePaySaveDtoList.stream().map(this::nodePayDtoToDao).collect(Collectors.toList());
    }

    private BamuContractNodePay nodePayDtoToDao(ContractNodePaySaveDto contractNodePaySaveDto) {
        BamuContractNodePay bamuContractNodePay = new BamuContractNodePay();
        BeanUtils.copyProperties(contractNodePaySaveDto, bamuContractNodePay);
        return bamuContractNodePay;
    }

    private List<ContractNodePayVO> nodePayDaoToVoList(List<BamuContractNodePay> records) {
        if (CollectionUtils.isEmpty(records)) {
            return Lists.newArrayList();
        }
        return records.stream().map(this::nodePayDaoToVo).collect(Collectors.toList());
    }

    private ContractNodePayVO nodePayDaoToVo(BamuContractNodePay bamuContractNodePay) {
        ContractNodePayVO contractNodePayVO = new ContractNodePayVO();
        BeanUtils.copyProperties(bamuContractNodePay, contractNodePayVO);
        return contractNodePayVO;
    }

    private List<SoSupplyMaterialVO> materialDaoToVoList(List<BamuSoSupplyMaterial> records) {
        return records.stream().map(this::materialDaoToVo).collect(Collectors.toList());
    }

    private SoSupplyMaterialVO materialDaoToVo(BamuSoSupplyMaterial bamuSoSupplyMaterial) {
        SoSupplyMaterialVO soSupplyMaterialVO = new SoSupplyMaterialVO();
        BamuSoSupply bamuSoSupply = iBamuSoSupplyService.getById(bamuSoSupplyMaterial.getSupplyId());
        BeanUtils.copyProperties(bamuSoSupplyMaterial, soSupplyMaterialVO);
        /**
         * BigDecimal保留4位小数
         */
        soSupplyMaterialVO.setReconciliationPrice(ConvertUtil.getBigDecimalValue(soSupplyMaterialVO.getIncludingTaxUnitPrice()).multiply(ConvertUtil.getBigDecimalValue(bamuSoSupplyMaterial.getComfirmSupplyNum())));
        soSupplyMaterialVO.setReconciliationPrice(soSupplyMaterialVO.getReconciliationPrice().setScale(4, RoundingMode.HALF_UP));
        if (Objects.nonNull(bamuSoSupply)) {
            soSupplyMaterialVO.setOrderSn(bamuSoSupply.getOrderSn());
            soSupplyMaterialVO.setReconciliation_order_sn(bamuSoSupply.getOrderSn());
        } else {
            soSupplyMaterialVO.setOrderSn("");
            soSupplyMaterialVO.setReconciliation_order_sn("");
        }
        return soSupplyMaterialVO;
    }

}
